/**
 * Copyright &copy; 2016-2017 <a href="http://git.oschina.net/whoamien/backend_management">Backend Management</a> All rights reserved.
 */
package com.xw.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;

/**
 * The Class DateUtil.
 *
 * @author Xi Wei
 * @version 1.0
 * @since 1.0
 */
public class DateUtil {
	
	/**  A log instance for this class. */

	// Dates constants

	/** "JAN" to represent January */
	public static final String MTH_JAN = "Jan";

	/**  "FEB" to represent February. */
	public static final String MTH_FEB = "Feb";

	/**  "MAR" to represent March. */
	public static final String MTH_MAR = "Mar";

	/**  "APR" to represent April. */
	public static final String MTH_APR = "Apr";

	/**  "MAY" to represent May. */
	public static final String MTH_MAY = "May";

	/**  "JUNE" to represent June. */
	public static final String MTH_JUN = "Jun";

	/**  "JUL" to represent July. */
	public static final String MTH_JUL = "Jul";

	/**  "AUG" to represent August. */
	public static final String MTH_AUG = "Aug";

	/**  "SEP" to represent September. */
	public static final String MTH_SEP = "Sep";

	/**  "OCT" to represent October. */
	public static final String MTH_OCT = "Oct";

	/**  "NOV" to represent November. */
	public static final String MTH_NOV = "Nov";

	/**  "DEC" to represent December. */
	public static final String MTH_DEC = "Dec";

	/**  The date pattern in this format 'ddMMyyyy HHmm'. */
	public static String DATETIME_FORMAT = "ddMMyyyy  HHmm";
	
	/** The date format. */
	public static String DATE_FORMAT = "dd MMM yyyy";
	
	/** The timestamp format. */
	public static String TIMESTAMP_FORMAT = "dd MMM yyyy HH:mm:ss";
	
	/** The input date format. */
	public static String INPUT_DATE_FORMAT = "ddMMyyyy";
	
	/** The time format. */
	public static String TIME_FORMAT = "HHmm";
	
	/** The datetime format a. */
	public static String DATETIME_FORMAT_A = "yyyyMMddHHmm";
	
	/** The Constant DATETIME_FORMAT_B. */
	public final static String DATETIME_FORMAT_B = "dd/MM/yyyy HH:mm:ss.SSS";
	
	/** The Constant DATETIME_FORMAT_C. */
	public final static String DATETIME_FORMAT_C = "yyyy,MM,dd,HH,mm";

	/**
	 * Gets the date.
	 *
	 * @param year the year
	 * @param month the month
	 * @param day the day
	 * @return the date
	 */
	public static Date getDate(int year, int month, int day) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day, 0, 0, 0);

		return cal.getTime();
	}

	/**
	 * Checks if is date equal.
	 *
	 * @param date1 the date 1
	 * @param date2 the date 2
	 * @return true, if is date equal
	 */
	public static boolean isDateEqual(Date date1, Date date2) {
		if ((date1 == null) || (date2 == null)) {
			return false;
		}

		return resetTime(date1).compareTo(resetTime(date2)) == 0;
	}

	/**
	 * Sets the default time zone.
	 *
	 * @param timeZoneID the new default time zone
	 */
	public static void setDefaultTimeZone(String timeZoneID) {
		TimeZone.setDefault(TimeZone.getTimeZone(timeZoneID));
	}

	/**
	 * Gets the elapsed time.
	 *
	 * @param type the type
	 * @param startDate the start date
	 * @param endDate the end date
	 * @return the elapsed time
	 */
	public static final int getElapsedTime(int type, Date startDate, Date endDate) {
		int elapsed = 0;

		if ((startDate == null) || (endDate == null)) {
			return -1;
		}

		if (startDate.after(endDate)) {
			return -1;
		}

		GregorianCalendar gc1 = (GregorianCalendar) GregorianCalendar.getInstance();
		GregorianCalendar gc2 = (GregorianCalendar) gc1.clone();
		gc1.setTime(startDate);
		gc2.setTime(endDate);

		gc1.clear(Calendar.MILLISECOND);
		gc1.clear(Calendar.SECOND);
		gc1.clear(Calendar.MINUTE);
		gc1.clear(Calendar.HOUR_OF_DAY);
		gc2.clear(Calendar.MILLISECOND);
		gc2.clear(Calendar.SECOND);
		gc2.clear(Calendar.MINUTE);
		gc2.clear(Calendar.HOUR_OF_DAY);

		if ((type != Calendar.MONTH) && (type != Calendar.YEAR)) {
			type = Calendar.DATE;
		}

		if (type == Calendar.MONTH) {
			gc1.clear(Calendar.DATE);
			gc2.clear(Calendar.DATE);
		}

		if (type == Calendar.YEAR) {
			gc1.clear(Calendar.DATE);
			gc2.clear(Calendar.DATE);
			gc1.clear(Calendar.MONTH);
			gc2.clear(Calendar.MONTH);
		}

		while (gc1.before(gc2)) {
			gc1.add(type, 1);
			elapsed++;
		}

		return elapsed;
	}

	/**
	 * Checks if is end of the month.
	 *
	 * @param date the date
	 * @return true, if is end of the month
	 */
	public static final boolean isEndOfTheMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);

		if (cal.get(Calendar.DATE) == maxDay) {
			return true;
		}

		return false;
	}

	/**
	 * Checks if is end of the year.
	 *
	 * @param date the date
	 * @return true, if is end of the year
	 */
	public static final boolean isEndOfTheYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		if ((cal.get(Calendar.MONTH) == 11) && (cal.get(Calendar.DATE) == 31)) {
			return true;
		}

		return false;
	}

	/**
	 * Gets the last day of the month.
	 *
	 * @param date the date
	 * @return the last day of the month
	 */
	public static final int getLastDayOfTheMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * Gets the mth in int.
	 *
	 * @param month the month
	 * @return the mth in int
	 */
	public static int getMthInInt(String month) {
		if (month.equalsIgnoreCase(MTH_JAN)) {
			return 1;
		} else if (month.equalsIgnoreCase(MTH_FEB)) {
			return 2;
		} else if (month.equalsIgnoreCase(MTH_MAR)) {
			return 3;
		} else if (month.equalsIgnoreCase(MTH_APR)) {
			return 4;
		} else if (month.equalsIgnoreCase(MTH_MAY)) {
			return 5;
		} else if (month.equalsIgnoreCase(MTH_JUN)) {
			return 6;
		} else if (month.equalsIgnoreCase(MTH_JUL)) {
			return 7;
		} else if (month.equalsIgnoreCase(MTH_AUG)) {
			return 8;
		} else if (month.equalsIgnoreCase(MTH_SEP)) {
			return 9;
		} else if (month.equalsIgnoreCase(MTH_OCT)) {
			return 10;
		} else if (month.equalsIgnoreCase(MTH_NOV)) {
			return 11;
		} else if (month.equalsIgnoreCase(MTH_DEC)) {
			return 12;
		} else {
			return 0;
		}
	}

	/**
	 * Gets the next working day.
	 *
	 * @return the next working day
	 */
	public static Date getNextWorkingDay() {
		Date nextWorkingDay = DateUtil.addDaysToDate(DateUtil.getSystemDate(), 1);
		Calendar c = Calendar.getInstance();
		c.setTime(nextWorkingDay);

		int day = c.get(Calendar.DAY_OF_WEEK);

		if (day == Calendar.SUNDAY) {
			nextWorkingDay = DateUtil.addDaysToDate(nextWorkingDay, 1);
		}

		return nextWorkingDay;
	}

	/**
	 * Checks if is start before end date.
	 *
	 * @param startDate the start date
	 * @param endDate the end date
	 * @return true, if is start before end date
	 */
	public static boolean isStartBeforeEndDate(Date startDate, Date endDate) {
		if ((startDate == null) || (endDate == null)) {
			return false;
		}

		return resetTime(startDate).compareTo(resetTime(endDate)) < 0;
	}

	/**
	 * Checks if is start of the month.
	 *
	 * @param date the date
	 * @return true, if is start of the month
	 */
	public static final boolean isStartOfTheMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		if (cal.get(Calendar.DATE) == 1) {
			return true;
		}

		return false;
	}

	/**
	 * Gets the month.
	 *
	 * @param date the date
	 * @return the month
	 */
	public static final int getMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal.get(Calendar.MONTH);

	}

	/**
	 * Gets the year.
	 *
	 * @param date the date
	 * @return the year
	 */
	public static final int getYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal.get(Calendar.YEAR);

	}

	/**
	 * Gets the day.
	 *
	 * @param date the date
	 * @return the day
	 */
	public static final int getDay(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal.get(Calendar.DAY_OF_MONTH);

	}

	/**
	 * Gets the week day.
	 *
	 * @param date the date
	 * @return the week day
	 */
	public static int getWeekDay(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * Checks if is start of the year.
	 *
	 * @param date the date
	 * @return true, if is start of the year
	 */
	public static final boolean isStartOfTheYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		if ((cal.get(Calendar.MONTH) == 1) && (cal.get(Calendar.DATE) == 1)) {
			return true;
		}

		return false;
	}

	/**
	 * Gets the str mth.
	 *
	 * @param month the month
	 * @return the str mth
	 */
	public static String getStrMth(int month) {
		if (month == 1) {
			return MTH_JAN;
		} else if (month == 2) {
			return MTH_FEB;
		} else if (month == 3) {
			return MTH_MAR;
		} else if (month == 4) {
			return MTH_APR;
		} else if (month == 5) {
			return MTH_MAY;
		} else if (month == 6) {
			return MTH_JUN;
		} else if (month == 7) {
			return MTH_JUL;
		} else if (month == 8) {
			return MTH_AUG;
		} else if (month == 9) {
			return MTH_SEP;
		} else if (month == 10) {
			return MTH_OCT;
		} else if (month == 11) {
			return MTH_NOV;
		} else if (month == 12) {
			return MTH_DEC;
		} else {
			return "";
		}
	}

	/**
	 * Compute duration.
	 *
	 * @param startDate the start date
	 * @param endDate the end date
	 * @return the int[]
	 */
	public static final int[] computeDuration(Date startDate, Date endDate) {
		Calendar from = Calendar.getInstance();
		Calendar to = Calendar.getInstance();
		from.setTime(startDate);
		to.setTime(endDate);

		int birthYYYY = from.get(Calendar.YEAR);
		int birthMM = from.get(Calendar.MONTH);
		int birthDD = from.get(Calendar.DAY_OF_MONTH);
		int asofYYYY = to.get(Calendar.YEAR);
		int asofMM = to.get(Calendar.MONTH);
		int asofDD = to.get(Calendar.DAY_OF_MONTH);
		int ageInYears = asofYYYY - birthYYYY;
		int ageInMonths = asofMM - birthMM;
		int ageInDays = asofDD - birthDD + 1;

		if (ageInDays < 0) {

			ageInDays += from.getActualMaximum(Calendar.DAY_OF_MONTH);
			ageInMonths--;
		}

		if (ageInDays == to.getActualMaximum(Calendar.DAY_OF_MONTH)) {
			ageInDays = 0;
			ageInMonths++;
		}

		if (ageInMonths < 0) {
			ageInMonths += 12;
			ageInYears--;
		}

		if ((birthYYYY < 0) && (asofYYYY > 0)) {
			ageInYears--;
		}

		if (ageInYears < 0) {
			ageInYears = 0;
			ageInMonths = 0;
			ageInDays = 0;
		}

		int[] result = new int[3];
		result[0] = ageInYears;
		result[1] = ageInMonths;
		result[2] = ageInDays;

		return result;
	}

	/**
	 * Gets the system date.
	 *
	 * @return the system date
	 */
	public static java.sql.Date getSystemDate() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		java.sql.Date sysDate = new java.sql.Date(cal.getTime().getTime());

		return sysDate;
	}

	/**
	 * Returns the current timestamp.
	 *
	 * @return Timestamp
	 */
	public static Timestamp getSystemTimestamp() {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * Checks if is valid year format.
	 *
	 * @param s the s
	 * @return true, if is valid year format
	 */
	public static boolean isValidYearFormat(String s) {
		if (s == null) {
			return false;
		} else if (s.trim().length() == 4) {
			return true;
		}

		return false;
	}

	/**
	 * Gets the date.
	 *
	 * @param date the date
	 * @param strFormat the str format
	 * @return the date
	 */
	public static String getDate(Date date, String strFormat) {
		return DateUtil.parseDate(date, strFormat);
	}

	/**
	 * Checks if is valid date.
	 *
	 * @param strDate the str date
	 * @return true, if is valid date
	 */
	public static boolean isValidDate(String strDate) {
		return DateUtil.toDate(strDate, "ddMMyyyy") != null;
	}

	/**
	 * Checks if is valid date.
	 *
	 * @param strDate the str date
	 * @param dateStrFormat the date str format
	 * @return true, if is valid date
	 */
	public static boolean isValidDate(String strDate, String dateStrFormat) {
		return DateUtil.toDate(strDate, dateStrFormat) != null;
	}

	/**
	 * Adds the date.
	 *
	 * @param type the type
	 * @param date the date
	 * @param num the num
	 * @return the date
	 */
	public static final Date addDate(int type, Date date, int num) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		cal.add(type, num);

		return new Date(cal.getTime().getTime());
	}

	/**
	 * Adds the days to date.
	 *
	 * @param date the date
	 * @param numDays the num days
	 * @return the date
	 */
	public static Date addDaysToDate(Date date, int numDays) {
		if (date == null) {
			return null;
		}

		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DATE, numDays);

		return c.getTime();
	}

	/**
	 * Adds the hours to date.
	 *
	 * @param date the date
	 * @param numHours the num hours
	 * @return the date
	 */
	public static Date addHoursToDate(Date date, int numHours) {
		if (date == null) {
			return null;
		}

		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.HOUR_OF_DAY, numHours);

		return c.getTime();
	}

	/**
	 * Adds the minutes to date.
	 *
	 * @param date the date
	 * @param numMins the num mins
	 * @return the date
	 */
	public static Date addMinutesToDate(Date date, int numMins) {
		if (date == null) {
			return null;
		}

		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MINUTE, numMins);

		return c.getTime();
	}

	/**
	 * Adds the months to date.
	 *
	 * @param date the date
	 * @param numMonths the num months
	 * @return the date
	 */
	public static Date addMonthsToDate(Date date, int numMonths) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MONTH, numMonths);
		return c.getTime();
	}

	/**
	 * Adds the years to date.
	 *
	 * @param date the date
	 * @param numYears the num years
	 * @return the date
	 */
	public static Date addYearsToDate(Date date, int numYears) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.YEAR, numYears);
		return c.getTime();
	}

	/**
	 * Compare dates.
	 *
	 * @param date1 the date 1
	 * @param date2 the date 2
	 * @return the int
	 */
	public static int compareDates(Date date1, Date date2) {
		if ((date1 == null) && (date2 == null)) {
			return 0;
		}

		if (date1 == null) {
			return -1;
		}

		if (date2 == null) {
			return 1;
		}

		String strFormat = "yyyyMMdd";
		SimpleDateFormat dateFormat = new SimpleDateFormat(strFormat);

		int intDate1 = Integer.parseInt(dateFormat.format(date1));
		int intDate2 = Integer.parseInt(dateFormat.format(date2));

		if (intDate1 == intDate2) {
			return 0;
		}

		if (intDate1 > intDate2) {
			return 1;
		}

		return -1;
	}

	/**
	 * Parses the date.
	 *
	 * @param date the date
	 * @param formatStr the format str
	 * @return the string
	 */
	public static String parseDate(Date date, String formatStr) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(formatStr);

		if (date == null) {
			return null;
		} else {
			return dateFormat.format(date);
		}
	}

	/**
	 * Parses the date.
	 *
	 * @param date the date
	 * @return the string
	 */
	public static String parseDate(Date date) {
		return parseDate(date, DATETIME_FORMAT);
	}

	/**
	 * Reset time.
	 *
	 * @param date the date
	 * @return the date
	 */
	public static Date resetTime(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	/**
	 * To date.
	 *
	 * @param strDateTime the str date time
	 * @param dateTimeFormat the date time format
	 * @return the date
	 */
	public static Date toDate(String strDateTime, String dateTimeFormat) {
		if ((strDateTime == null) || (strDateTime.trim().length() == 0) || (dateTimeFormat == null)
				|| (dateTimeFormat.trim().length() == 0)) {
			return null;
		}

		SimpleDateFormat dateFormat = new SimpleDateFormat(dateTimeFormat.trim());
		Date date = dateFormat.parse(strDateTime.trim(), new ParsePosition(0));

		if (date == null) {
			return null;
		}

		String dateStr = parseDate(date, dateTimeFormat.trim());

		if (!strDateTime.trim().equals(dateStr)) {
			return null;
		}

		return date;
	}

	/**
	 * To date.
	 *
	 * @param strDateTime the str date time
	 * @return the date
	 */
	public static Date toDate(String strDateTime) {
		return toDate(strDateTime, DATETIME_FORMAT);
	}

	/**
	 * To date.
	 *
	 * @param hour the hour
	 * @param minute the minute
	 * @param second the second
	 * @param millisecond the millisecond
	 * @return the date
	 */
	public static Date toDate(int hour, int minute, int second, int millisecond) {
		Calendar cal = Calendar.getInstance();

		cal.set(1970, 0, 1);
		cal.set(Calendar.HOUR_OF_DAY, hour);
		cal.set(Calendar.MINUTE, minute);
		cal.set(Calendar.SECOND, second);
		cal.set(Calendar.MILLISECOND, millisecond);

		return new Date(cal.getTime().getTime());
	}

	/**
	 * To MM format.
	 *
	 * @param mthMMM the mth MMM
	 * @return the string
	 */
	public static String toMMFormat(String mthMMM) {
		if (mthMMM.equalsIgnoreCase(MTH_JAN)) {
			return "01";
		} else if (mthMMM.equalsIgnoreCase(MTH_FEB)) {
			return "02";
		} else if (mthMMM.equalsIgnoreCase(MTH_MAR)) {
			return "03";
		} else if (mthMMM.equalsIgnoreCase(MTH_APR)) {
			return "04";
		} else if (mthMMM.equalsIgnoreCase(MTH_MAY)) {
			return "05";
		} else if (mthMMM.equalsIgnoreCase(MTH_JUN)) {
			return "06";
		} else if (mthMMM.equalsIgnoreCase(MTH_JUL)) {
			return "07";
		} else if (mthMMM.equalsIgnoreCase(MTH_AUG)) {
			return "08";
		} else if (mthMMM.equalsIgnoreCase(MTH_SEP)) {
			return "09";
		} else if (mthMMM.equalsIgnoreCase(MTH_OCT)) {
			return "10";
		} else if (mthMMM.equalsIgnoreCase(MTH_NOV)) {
			return "11";
		} else if (mthMMM.equalsIgnoreCase(MTH_DEC)) {
			return "12";
		}

		return null;
	}

	/**
	 * To MMM format.
	 *
	 * @param mthMM the mth MM
	 * @return the string
	 */
	public static String toMMMFormat(String mthMM) {
		if ("01".equals(mthMM)) {
			return MTH_JAN;
		} else if ("02".equals(mthMM)) {
			return MTH_FEB;
		} else if ("03".equals(mthMM)) {
			return MTH_MAR;
		} else if ("04".equals(mthMM)) {
			return MTH_APR;
		} else if ("05".equals(mthMM)) {
			return MTH_MAY;
		} else if ("06".equals(mthMM)) {
			return MTH_JUN;
		} else if ("07".equals(mthMM)) {
			return MTH_JUL;
		} else if ("08".equals(mthMM)) {
			return MTH_AUG;
		} else if ("09".equals(mthMM)) {
			return MTH_SEP;
		} else if ("10".equals(mthMM)) {
			return MTH_OCT;
		} else if ("11".equals(mthMM)) {
			return MTH_NOV;
		} else if ("12".equals(mthMM)) {
			return MTH_DEC;
		}

		return null;
	}

	/**
	 * To SQL date.
	 *
	 * @param strDateTime the str date time
	 * @param dateTimeFormat the date time format
	 * @return the java.sql. date
	 */
	public static java.sql.Date toSQLDate(String strDateTime, String dateTimeFormat) {
		Date date = toDate(strDateTime, dateTimeFormat);

		if (date == null) {
			return null;
		}

		return new java.sql.Date(date.getTime());
	}

	/**
	 * To SQL date.
	 *
	 * @param date the date
	 * @return the java.sql. date
	 */
	public static java.sql.Date toSQLDate(Date date) {
		if (date == null) {
			return null;
		}

		return new java.sql.Date(date.getTime());
	}

	/**
	 * To SQL date.
	 *
	 * @param strDateTime the str date time
	 * @return the java.sql. date
	 */
	public static java.sql.Date toSQLDate(String strDateTime) {
		return toSQLDate(strDateTime, DATETIME_FORMAT);
	}

	/**
	 * To timestamp.
	 *
	 * @param dateTimeStr the date time str
	 * @return the timestamp
	 */
	public static Timestamp toTimestamp(String dateTimeStr) {
		return toTimestamp(toDate(dateTimeStr));
	}

	/**
	 * To timestamp.
	 *
	 * @param dateTimeStr the date time str
	 * @param dateTimeFormat the date time format
	 * @return the timestamp
	 */
	public static Timestamp toTimestamp(String dateTimeStr, String dateTimeFormat) {
		return toTimestamp(toDate(dateTimeStr, dateTimeFormat));
	}

	/**
	 * To timestamp.
	 *
	 * @param date the date
	 * @return the timestamp
	 */
	public static Timestamp toTimestamp(Date date) {
		if (date == null) {
			return null;
		}

		return new Timestamp(date.getTime());
	}

	/**
	 * To date.
	 *
	 * @param timeStamp the time stamp
	 * @return the date
	 */
	public static Date toDate(Timestamp timeStamp) {
		if (timeStamp == null) {
			return null;
		}

		return new Date(timeStamp.getTime());
	}

	/**
	 * To two digits.
	 *
	 * @param number the number
	 * @return the string
	 */
	public static String toTwoDigits(String number) {
		return StringUtil.lPad(number, 2, "0");
	}

	/**
	 * Gets the duration dates.
	 *
	 * @param originalJobDate the original job date
	 * @param months the months
	 * @param days the days
	 * @return the duration dates
	 */
	public static java.util.Date[] getDurationDates(Date originalJobDate, float months, int days) {
		if (originalJobDate == null) {
			return null;
		}

		java.util.Date[] expireDates;
		Calendar markedDate = Calendar.getInstance();
		markedDate.setTime(originalJobDate);

		int iMonths = (int) months;
		int iDays = days + Math.round(30 * (months - iMonths));

		if (months < 0) {
			markedDate.add(Calendar.DATE, iDays);
			Calendar tempDate = (Calendar) markedDate.clone();
			markedDate.add(Calendar.MONTH, iMonths);

			int dayTmp = tempDate.get(Calendar.DATE);
			int maxDaysTmp = tempDate.getActualMaximum(Calendar.DATE);
			int day = markedDate.get(Calendar.DATE);
			int maxDays = markedDate.getActualMaximum(Calendar.DATE);

			if (dayTmp > day) {
				expireDates = null;
			} else if (dayTmp == maxDaysTmp && day < maxDays) {
				expireDates = new Date[maxDays - day + 1];
				for (int i = 0; i < expireDates.length; i++) {
					expireDates[i] = markedDate.getTime();
					markedDate.set(Calendar.DATE, ++day);
				}
			} else {
				expireDates = new Date[1];
				expireDates[0] = markedDate.getTime();
			}
		} else {
			expireDates = new Date[1];
			markedDate.add(Calendar.MONTH, iMonths);
			markedDate.add(Calendar.DATE, iDays);
			expireDates[0] = markedDate.getTime();
		}

		return expireDates;
	}

	/**
	 * Date converter.
	 *
	 * @param dateIn the date in
	 * @param formatIn the format in
	 * @param formatOut the format out
	 * @return the string
	 */
	public static String DateConverter(String dateIn, String formatIn, String formatOut) {
		try {
			if ("now".equalsIgnoreCase(dateIn)) {
				return (new SimpleDateFormat(formatOut).format(new Date()));
			} else {
				return (new SimpleDateFormat(formatOut))
						.format((new SimpleDateFormat(formatIn)).parse(dateIn, new ParsePosition(0)));
			}
		} catch (Exception e) {
			return "";
		}
	}

	/**
	 * Gets the next start month year.
	 *
	 * @param currentDate the current date
	 * @return the next start month year
	 */
	public static Timestamp getNextStartMonthYear(Date currentDate) {
		// Date currentDate = getSystemDate();
		int currentMonth = getMonth(currentDate) + 1;
		int nextYear = getYear(currentDate);
		int nextMonth = 1; // January by default

		if (currentMonth <= 11) { // if current month is jan to nov
			nextMonth = currentMonth + 1;
		}

		if (nextMonth == 1) { // means that the currentMonth is dec.
			nextYear++;
		}

		return toTimestamp(getDate(nextYear, nextMonth, 1));
	}

	/**
	 * Gets the next end month year.
	 *
	 * @param currentDate the current date
	 * @return the next end month year
	 */
	public static Timestamp getNextEndMonthYear(Date currentDate) {
		Date nextStartMonthYear = getNextStartMonthYear(currentDate);
		int lastDay = getLastDayOfTheMonth(nextStartMonthYear);
		return toTimestamp(getDate(getYear(nextStartMonthYear), getMonth(nextStartMonthYear) + 1, lastDay));
	}

	/**
	 * Checks if is valid time.
	 *
	 * @param strTime the str time
	 * @return true, if is valid time
	 */
	public static boolean isValidTime(String strTime) {
		boolean isValid = false;
		if (strTime.length() == 4) {
			if (Integer.parseInt(strTime) >= 0 && Integer.parseInt(strTime) <= 2359) {
				isValid = true;
			}
		}
		return isValid;
	}

	/**
	 * Checks if is valid time range.
	 *
	 * @param strTimeStart the str time start
	 * @param strTimeEnd the str time end
	 * @return true, if is valid time range
	 */
	public static boolean isValidTimeRange(String strTimeStart, String strTimeEnd) {
		boolean isValid = true;
		if (Integer.parseInt(strTimeEnd) < Integer.parseInt(strTimeStart)) {
			isValid = false;
		}
		return isValid;
	}

	/**
	 * To timestamp string date time.
	 *
	 * @param strDate the str date
	 * @param strTime the str time
	 * @return the timestamp
	 */
	public static Timestamp toTimestampStringDateTime(String strDate, String strTime) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATETIME_FORMAT);
		Timestamp timestamp = null;
		java.util.Date parsedDate;
		try {
			parsedDate = dateFormat.parse(strDate + "  " + strTime);
			timestamp = new java.sql.Timestamp(parsedDate.getTime());
		} catch (ParseException e) {
			Log.logExceptionStackTrack(e);
		}
		return timestamp;
	}

	/**
	 * Gets the current SQL date.
	 *
	 * @return the current SQL date
	 */
	public static java.sql.Date getCurrentSQLDate() {

		Calendar calendar = Calendar.getInstance();
		java.sql.Date jsqlD = new java.sql.Date(calendar.getTime().getTime());
		return jsqlD;
	}

	/**
	 * Compare date with time.
	 *
	 * @param date1 the date 1
	 * @param date2 the date 2
	 * @return the int
	 */
	public static int compareDateWithTime(Date date1, Date date2) {

		if ((date1 == null) && (date2 == null)) {
			return 0;
		}

		if (date1 == null) {
			return -1;
		}

		if (date2 == null) {
			return 1;
		}

		if (date1.getTime() < date2.getTime()) {
			return -1;
		}

		if (date1.getTime() > date2.getTime()) {
			return 1;
		}

		return 0;

	}

	/**
	 * Gets the date time difference.
	 *
	 * @param startDate the start date
	 * @param endDate the end date
	 * @return the date time difference
	 */
	public static long getDateTimeDifference(Date startDate, Date endDate) {

		if ((startDate == null) || (endDate == null)) {
			return -1;
		}

		if (startDate.after(endDate)) {
			return -1;
		}

		GregorianCalendar gc1 = (GregorianCalendar) GregorianCalendar.getInstance();
		GregorianCalendar gc2 = (GregorianCalendar) gc1.clone();
		gc1.setTime(startDate);
		gc2.setTime(endDate);
		long milis1 = gc1.getTimeInMillis();
		long milis2 = gc2.getTimeInMillis();

		long diff = milis2 - milis1;

		long diffMinutes = diff / (60 * 1000);

		return diffMinutes;
	}

	/**
	 * Gets the the month before current month.
	 *
	 * @return the the month before current month
	 */
	public static int[] getTheMonthBeforeCurrentMonth() {
		int[] rs = new int[2];

		GregorianCalendar gc1 = (GregorianCalendar) GregorianCalendar.getInstance();
		int currentYear = gc1.get(Calendar.YEAR);
		int currentMonth = gc1.get(Calendar.MONTH) + 1; // start from 0

		if (currentMonth > 1) {
			rs[0] = currentYear;
			rs[1] = currentMonth - 1;
		} else {
			rs[0] = currentYear - 1;
			rs[1] = 12;
		}

		return rs;

	}

	/**
	 * Gets the end of the day.
	 *
	 * @param date the date
	 * @return the end of the day
	 */
	public static Date getEndOfTheDay(Date date) {
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);

		return cal.getTime();
	}

	/**
	 * Gets the end of the day.
	 *
	 * @param date the date
	 * @return the end of the day
	 */
	public static Timestamp getEndOfTheDay(Timestamp date) {
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);

		return new Timestamp(cal.getTimeInMillis());
	}

	/**
	 * Gets the end of the month.
	 *
	 * @param date the date
	 * @return the end of the month
	 */
	public static Date getEndOfTheMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);

		return new Timestamp(cal.getTimeInMillis());
	}

	/**
	 * Gets the begin of the day.
	 *
	 * @param date the date
	 * @return the begin of the day
	 */
	public static Date getBeginOfTheDay(Date date) {
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	/**
	 * Gets the begin of the year.
	 *
	 * @param date the date
	 * @return the begin of the year
	 */
	public static Date getBeginOfTheYear(Date date) {
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.set(Calendar.MONTH, Calendar.JANUARY);
		cal.set(Calendar.DATE, 1);

		return cal.getTime();
	}

	/**
	 * Gets the monthly first and last day.
	 *
	 * @return the monthly first and last day
	 */
	public static List getMonthlyFirstAndLastDay() {

		List dateList = new ArrayList();

		Calendar cal = Calendar.getInstance();
		cal.add(cal.MONTH, 1);
		cal.set(cal.DATE, 1);
		cal.add(cal.DATE, -1);
		java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("MM/dd/yyyy");
		String day_end = df.format(cal.getTime());
		Calendar c = Calendar.getInstance();
		c.set(c.DATE, 1);
		dateList.add(df.format(c.getTime()));
		dateList.add(day_end);
		return dateList;
	}

	/**
	 * First day of week.
	 *
	 * @param dateStr the date str
	 * @return the date
	 * @throws Exception the exception
	 */
	public static Date firstDayOfWeek(String dateStr) throws Exception {

		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");

		cal.setTime(sdf.parse(dateStr));

		int day_of_week = cal.get(Calendar.DAY_OF_WEEK);
		// Log4J.info("The date is: " + cal.getTime() +" day of week="+
		// day_of_week);
		if (day_of_week == 1) {
			day_of_week = 6;
		} else if (day_of_week == 7) {
			day_of_week = 5;
		} else if (day_of_week == 6) {
			day_of_week = 4;
		} else if (day_of_week == 5) {
			day_of_week = 3;
		} else if (day_of_week == 4) {
			day_of_week = 2;
		} else if (day_of_week == 3) {
			day_of_week = 1;
		} else if (day_of_week == 2) {
			day_of_week = 0;
		}

		cal.add(Calendar.DATE, -day_of_week);
		// Log4J.info("first day of this week: " + cal.getTime() );
		return cal.getTime();

	}

	/**
	 * Last day of week.
	 *
	 * @param dateStr the date str
	 * @return the date
	 * @throws Exception the exception
	 */
	public static Date lastDayOfWeek(String dateStr) throws Exception {

		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");

		cal.setTime(sdf.parse(dateStr));

		int day_of_week = cal.get(Calendar.DAY_OF_WEEK);
		// Log4J.info("The date is: " + cal.getTime() +" day of week="+
		// day_of_week);
		if (day_of_week == 1) {
			day_of_week = 6;
		} else if (day_of_week == 7) {
			day_of_week = 5;
		} else if (day_of_week == 6) {
			day_of_week = 4;
		} else if (day_of_week == 5) {
			day_of_week = 3;
		} else if (day_of_week == 4) {
			day_of_week = 2;
		} else if (day_of_week == 3) {
			day_of_week = 1;
		} else if (day_of_week == 2) {
			day_of_week = 0;
		}

		cal.add(Calendar.DATE, -day_of_week);
		cal.add(Calendar.DATE, 6);
		// Log4J.info("Last day of this week: " + cal.getTime() );
		return cal.getTime();

	}

	/**
	 * Late hour.
	 *
	 * @param date the date
	 * @param hour the hour
	 * @return the calendar
	 */
	public static Calendar lateHour(Date date, Integer hour) {
		Calendar rightNow = Calendar.getInstance();
		rightNow.setTime(date);

		rightNow.set(Calendar.HOUR_OF_DAY, rightNow.get(Calendar.HOUR_OF_DAY) + hour);
		// 得到当前时间，+3天
		// 如果是后退几天，就写 -天数 例如：
		// rightNow.add(java.util.Calendar.DAY_OF_MONTH, -3);
		// 进行时间转换
		return rightNow;
	}

	/**
	 * Gets the previous month.
	 *
	 * @param date the date
	 * @return the previous month
	 */
	public static int getPreviousMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, -1);

		return cal.get(Calendar.MONTH);
	}

	/**
	 * Gets the.
	 *
	 * @param date the date
	 * @param type the type
	 * @return the int
	 */
	public static int get(Date date, int type) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(type);
	}

}
